Skip to content

feat(identity): sync address book contacts #5776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

fabiobozzo
Copy link
Contributor

@fabiobozzo fabiobozzo commented May 7, 2025

Explanation

The current implementation of MetaMask's address book (contacts) lacks the ability to synchronize between devices. While we recently implemented this capability for accounts using encrypted user storage, the address book remained local to each device.
This PR implements backup-and-sync functionality for the address book controller, similar to what was already implemented for the accounts controller.

Implementation notes

  1. Creates a dedicated integration in the profile-sync-controller package with:
  • Type definitions for address book storage entries
  • Conversion utilities between controller and storage formats
  • Sync logic to handle bidirectional synchronization
  1. Event subscriptions to trigger syncs on contact update/deletion
  2. Updates the UserStorageController to properly handle address book data

References

Needed by: MetaMask/metamask-extension#32632
Depends on: #5779

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed, highlighting breaking changes as necessary
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

Copy link

socket-security bot commented May 19, 2025

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

@fabiobozzo fabiobozzo changed the title feat(identity): sync address book feat(identity): sync address book contacts May 22, 2025
fabiobozzo added a commit that referenced this pull request May 26, 2025
## Explanation

- Emit events on contact updates and deletions. 
- List method to retrieve contacts stored locally.

## References

Needed by: #5776

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs),
highlighting breaking changes as necessary
- [x] I've prepared draft pull requests for clients and consumer
packages to resolve any breaking changes

---------

Co-authored-by: Mathieu Artu <[email protected]>
@fabiobozzo fabiobozzo marked this pull request as ready for review May 26, 2025 10:59
@fabiobozzo fabiobozzo requested review from a team as code owners May 26, 2025 10:59
@fabiobozzo
Copy link
Contributor Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "29.0.0-preview-e7141654",
  "@metamask-previews/address-book-controller": "6.0.3-preview-e7141654",
  "@metamask-previews/announcement-controller": "7.0.3-preview-e7141654",
  "@metamask-previews/app-metadata-controller": "1.0.0-preview-e7141654",
  "@metamask-previews/approval-controller": "7.1.3-preview-e7141654",
  "@metamask-previews/assets-controllers": "64.0.0-preview-e7141654",
  "@metamask-previews/base-controller": "8.0.1-preview-e7141654",
  "@metamask-previews/bridge-controller": "27.0.0-preview-e7141654",
  "@metamask-previews/bridge-status-controller": "24.0.0-preview-e7141654",
  "@metamask-previews/build-utils": "3.0.3-preview-e7141654",
  "@metamask-previews/chain-agnostic-permission": "0.7.0-preview-e7141654",
  "@metamask-previews/composable-controller": "11.0.0-preview-e7141654",
  "@metamask-previews/controller-utils": "11.9.0-preview-e7141654",
  "@metamask-previews/delegation-controller": "0.3.0-preview-e7141654",
  "@metamask-previews/earn-controller": "0.14.0-preview-e7141654",
  "@metamask-previews/eip1193-permission-middleware": "0.1.0-preview-e7141654",
  "@metamask-previews/ens-controller": "16.0.0-preview-e7141654",
  "@metamask-previews/error-reporting-service": "0.0.0-preview-e7141654",
  "@metamask-previews/eth-json-rpc-provider": "4.1.8-preview-e7141654",
  "@metamask-previews/gas-fee-controller": "23.0.0-preview-e7141654",
  "@metamask-previews/json-rpc-engine": "10.0.3-preview-e7141654",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.7-preview-e7141654",
  "@metamask-previews/keyring-controller": "22.0.0-preview-e7141654",
  "@metamask-previews/logging-controller": "6.0.4-preview-e7141654",
  "@metamask-previews/message-manager": "12.0.1-preview-e7141654",
  "@metamask-previews/multichain": "4.1.0-preview-e7141654",
  "@metamask-previews/multichain-api-middleware": "0.3.0-preview-e7141654",
  "@metamask-previews/multichain-network-controller": "0.7.0-preview-e7141654",
  "@metamask-previews/multichain-transactions-controller": "1.0.0-preview-e7141654",
  "@metamask-previews/name-controller": "8.0.3-preview-e7141654",
  "@metamask-previews/network-controller": "23.5.0-preview-e7141654",
  "@metamask-previews/notification-services-controller": "8.0.0-preview-e7141654",
  "@metamask-previews/permission-controller": "11.0.6-preview-e7141654",
  "@metamask-previews/permission-log-controller": "3.0.3-preview-e7141654",
  "@metamask-previews/phishing-controller": "12.5.0-preview-e7141654",
  "@metamask-previews/polling-controller": "13.0.0-preview-e7141654",
  "@metamask-previews/preferences-controller": "18.0.0-preview-e7141654",
  "@metamask-previews/profile-sync-controller": "15.0.0-preview-e7141654",
  "@metamask-previews/queued-request-controller": "10.0.0-preview-e7141654",
  "@metamask-previews/rate-limit-controller": "6.0.3-preview-e7141654",
  "@metamask-previews/remote-feature-flag-controller": "1.6.0-preview-e7141654",
  "@metamask-previews/sample-controllers": "0.1.0-preview-e7141654",
  "@metamask-previews/selected-network-controller": "22.1.0-preview-e7141654",
  "@metamask-previews/signature-controller": "29.0.0-preview-e7141654",
  "@metamask-previews/token-search-discovery-controller": "3.1.0-preview-e7141654",
  "@metamask-previews/transaction-controller": "56.2.0-preview-e7141654",
  "@metamask-previews/user-operation-controller": "35.0.0-preview-e7141654"
}

@fabiobozzo
Copy link
Contributor Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "29.0.0-preview-2f320f7a",
  "@metamask-previews/address-book-controller": "6.0.3-preview-2f320f7a",
  "@metamask-previews/announcement-controller": "7.0.3-preview-2f320f7a",
  "@metamask-previews/app-metadata-controller": "1.0.0-preview-2f320f7a",
  "@metamask-previews/approval-controller": "7.1.3-preview-2f320f7a",
  "@metamask-previews/assets-controllers": "64.0.0-preview-2f320f7a",
  "@metamask-previews/base-controller": "8.0.1-preview-2f320f7a",
  "@metamask-previews/bridge-controller": "27.0.0-preview-2f320f7a",
  "@metamask-previews/bridge-status-controller": "24.0.0-preview-2f320f7a",
  "@metamask-previews/build-utils": "3.0.3-preview-2f320f7a",
  "@metamask-previews/chain-agnostic-permission": "0.7.0-preview-2f320f7a",
  "@metamask-previews/composable-controller": "11.0.0-preview-2f320f7a",
  "@metamask-previews/controller-utils": "11.9.0-preview-2f320f7a",
  "@metamask-previews/delegation-controller": "0.3.0-preview-2f320f7a",
  "@metamask-previews/earn-controller": "0.14.0-preview-2f320f7a",
  "@metamask-previews/eip1193-permission-middleware": "0.1.0-preview-2f320f7a",
  "@metamask-previews/ens-controller": "16.0.0-preview-2f320f7a",
  "@metamask-previews/error-reporting-service": "0.0.0-preview-2f320f7a",
  "@metamask-previews/eth-json-rpc-provider": "4.1.8-preview-2f320f7a",
  "@metamask-previews/gas-fee-controller": "23.0.0-preview-2f320f7a",
  "@metamask-previews/json-rpc-engine": "10.0.3-preview-2f320f7a",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.7-preview-2f320f7a",
  "@metamask-previews/keyring-controller": "22.0.0-preview-2f320f7a",
  "@metamask-previews/logging-controller": "6.0.4-preview-2f320f7a",
  "@metamask-previews/message-manager": "12.0.1-preview-2f320f7a",
  "@metamask-previews/multichain": "4.1.0-preview-2f320f7a",
  "@metamask-previews/multichain-api-middleware": "0.3.0-preview-2f320f7a",
  "@metamask-previews/multichain-network-controller": "0.7.0-preview-2f320f7a",
  "@metamask-previews/multichain-transactions-controller": "1.0.0-preview-2f320f7a",
  "@metamask-previews/name-controller": "8.0.3-preview-2f320f7a",
  "@metamask-previews/network-controller": "23.5.0-preview-2f320f7a",
  "@metamask-previews/notification-services-controller": "8.0.0-preview-2f320f7a",
  "@metamask-previews/permission-controller": "11.0.6-preview-2f320f7a",
  "@metamask-previews/permission-log-controller": "3.0.3-preview-2f320f7a",
  "@metamask-previews/phishing-controller": "12.5.0-preview-2f320f7a",
  "@metamask-previews/polling-controller": "13.0.0-preview-2f320f7a",
  "@metamask-previews/preferences-controller": "18.0.0-preview-2f320f7a",
  "@metamask-previews/profile-sync-controller": "15.0.0-preview-2f320f7a",
  "@metamask-previews/queued-request-controller": "10.0.0-preview-2f320f7a",
  "@metamask-previews/rate-limit-controller": "6.0.3-preview-2f320f7a",
  "@metamask-previews/remote-feature-flag-controller": "1.6.0-preview-2f320f7a",
  "@metamask-previews/sample-controllers": "0.1.0-preview-2f320f7a",
  "@metamask-previews/selected-network-controller": "22.1.0-preview-2f320f7a",
  "@metamask-previews/signature-controller": "29.0.0-preview-2f320f7a",
  "@metamask-previews/token-search-discovery-controller": "3.1.0-preview-2f320f7a",
  "@metamask-previews/transaction-controller": "56.2.0-preview-2f320f7a",
  "@metamask-previews/user-operation-controller": "35.0.0-preview-2f320f7a"
}

@fabiobozzo
Copy link
Contributor Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "29.0.1-preview-2723071f",
  "@metamask-previews/address-book-controller": "6.0.3-preview-2723071f",
  "@metamask-previews/announcement-controller": "7.0.3-preview-2723071f",
  "@metamask-previews/app-metadata-controller": "1.0.0-preview-2723071f",
  "@metamask-previews/approval-controller": "7.1.3-preview-2723071f",
  "@metamask-previews/assets-controllers": "66.0.0-preview-2723071f",
  "@metamask-previews/base-controller": "8.0.1-preview-2723071f",
  "@metamask-previews/bridge-controller": "29.0.0-preview-2723071f",
  "@metamask-previews/bridge-status-controller": "26.0.0-preview-2723071f",
  "@metamask-previews/build-utils": "3.0.3-preview-2723071f",
  "@metamask-previews/chain-agnostic-permission": "0.7.0-preview-2723071f",
  "@metamask-previews/composable-controller": "11.0.0-preview-2723071f",
  "@metamask-previews/controller-utils": "11.9.0-preview-2723071f",
  "@metamask-previews/delegation-controller": "0.3.0-preview-2723071f",
  "@metamask-previews/earn-controller": "0.14.0-preview-2723071f",
  "@metamask-previews/eip1193-permission-middleware": "0.1.0-preview-2723071f",
  "@metamask-previews/ens-controller": "16.0.0-preview-2723071f",
  "@metamask-previews/error-reporting-service": "1.0.0-preview-2723071f",
  "@metamask-previews/eth-json-rpc-provider": "4.1.8-preview-2723071f",
  "@metamask-previews/gas-fee-controller": "23.0.0-preview-2723071f",
  "@metamask-previews/json-rpc-engine": "10.0.3-preview-2723071f",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.7-preview-2723071f",
  "@metamask-previews/keyring-controller": "22.0.0-preview-2723071f",
  "@metamask-previews/logging-controller": "6.0.4-preview-2723071f",
  "@metamask-previews/message-manager": "12.0.1-preview-2723071f",
  "@metamask-previews/multichain": "4.1.0-preview-2723071f",
  "@metamask-previews/multichain-api-middleware": "0.4.0-preview-2723071f",
  "@metamask-previews/multichain-network-controller": "0.7.0-preview-2723071f",
  "@metamask-previews/multichain-transactions-controller": "1.0.0-preview-2723071f",
  "@metamask-previews/name-controller": "8.0.3-preview-2723071f",
  "@metamask-previews/network-controller": "23.5.1-preview-2723071f",
  "@metamask-previews/notification-services-controller": "8.0.0-preview-2723071f",
  "@metamask-previews/permission-controller": "11.0.6-preview-2723071f",
  "@metamask-previews/permission-log-controller": "3.0.3-preview-2723071f",
  "@metamask-previews/phishing-controller": "12.5.0-preview-2723071f",
  "@metamask-previews/polling-controller": "13.0.0-preview-2723071f",
  "@metamask-previews/preferences-controller": "18.1.0-preview-2723071f",
  "@metamask-previews/profile-sync-controller": "15.0.0-preview-2723071f",
  "@metamask-previews/queued-request-controller": "10.0.0-preview-2723071f",
  "@metamask-previews/rate-limit-controller": "6.0.3-preview-2723071f",
  "@metamask-previews/remote-feature-flag-controller": "1.6.0-preview-2723071f",
  "@metamask-previews/sample-controllers": "0.1.0-preview-2723071f",
  "@metamask-previews/seedless-onboarding-controller": "0.0.0-preview-2723071f",
  "@metamask-previews/selected-network-controller": "22.1.0-preview-2723071f",
  "@metamask-previews/signature-controller": "29.0.0-preview-2723071f",
  "@metamask-previews/token-search-discovery-controller": "3.2.0-preview-2723071f",
  "@metamask-previews/transaction-controller": "56.3.0-preview-2723071f",
  "@metamask-previews/user-operation-controller": "35.0.0-preview-2723071f"
}

@fabiobozzo fabiobozzo requested a review from mirceanis June 2, 2025 11:05
Comment on lines +235 to +238
if (onContactSyncErroneousSituation) {
onContactSyncErroneousSituation('Error synchronizing contacts', {
error,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should still throw the actual error here, as to me this is a real error and not an erroneous situation. FYI, we introduced the concept of erroneous situations for account syncing because we detected weird behaviors that didn't align with our other metrics, and wanted to understand corner cases.
For contacts, we might not want to have the concept of "erroneous situations" at all, at least for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might encounter erroneous situations with contact syncing as well, imho. 🤔 Especially bc of deletions.
I'd prefer to leave the callback in place, and just re-throw the error, for now.

@fabiobozzo
Copy link
Contributor Author

@metamaskbot publish-preview

Copy link
Contributor

github-actions bot commented Jun 3, 2025

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "30.0.0-preview-510657d5",
  "@metamask-previews/address-book-controller": "6.0.3-preview-510657d5",
  "@metamask-previews/announcement-controller": "7.0.3-preview-510657d5",
  "@metamask-previews/app-metadata-controller": "1.0.0-preview-510657d5",
  "@metamask-previews/approval-controller": "7.1.3-preview-510657d5",
  "@metamask-previews/assets-controllers": "68.0.0-preview-510657d5",
  "@metamask-previews/base-controller": "8.0.1-preview-510657d5",
  "@metamask-previews/bridge-controller": "32.0.0-preview-510657d5",
  "@metamask-previews/bridge-status-controller": "29.0.0-preview-510657d5",
  "@metamask-previews/build-utils": "3.0.3-preview-510657d5",
  "@metamask-previews/chain-agnostic-permission": "0.7.0-preview-510657d5",
  "@metamask-previews/composable-controller": "11.0.0-preview-510657d5",
  "@metamask-previews/controller-utils": "11.9.0-preview-510657d5",
  "@metamask-previews/delegation-controller": "0.4.0-preview-510657d5",
  "@metamask-previews/earn-controller": "0.15.0-preview-510657d5",
  "@metamask-previews/eip1193-permission-middleware": "0.1.0-preview-510657d5",
  "@metamask-previews/ens-controller": "16.0.0-preview-510657d5",
  "@metamask-previews/error-reporting-service": "1.0.0-preview-510657d5",
  "@metamask-previews/eth-json-rpc-provider": "4.1.8-preview-510657d5",
  "@metamask-previews/gas-fee-controller": "23.0.0-preview-510657d5",
  "@metamask-previews/json-rpc-engine": "10.0.3-preview-510657d5",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.7-preview-510657d5",
  "@metamask-previews/keyring-controller": "22.0.1-preview-510657d5",
  "@metamask-previews/logging-controller": "6.0.4-preview-510657d5",
  "@metamask-previews/message-manager": "12.0.1-preview-510657d5",
  "@metamask-previews/multichain": "4.1.0-preview-510657d5",
  "@metamask-previews/multichain-api-middleware": "0.4.0-preview-510657d5",
  "@metamask-previews/multichain-network-controller": "0.8.0-preview-510657d5",
  "@metamask-previews/multichain-transactions-controller": "2.0.0-preview-510657d5",
  "@metamask-previews/name-controller": "8.0.3-preview-510657d5",
  "@metamask-previews/network-controller": "23.5.1-preview-510657d5",
  "@metamask-previews/notification-services-controller": "9.0.0-preview-510657d5",
  "@metamask-previews/permission-controller": "11.0.6-preview-510657d5",
  "@metamask-previews/permission-log-controller": "3.0.3-preview-510657d5",
  "@metamask-previews/phishing-controller": "12.5.0-preview-510657d5",
  "@metamask-previews/polling-controller": "13.0.0-preview-510657d5",
  "@metamask-previews/preferences-controller": "18.1.0-preview-510657d5",
  "@metamask-previews/profile-sync-controller": "16.0.0-preview-510657d5",
  "@metamask-previews/queued-request-controller": "10.0.0-preview-510657d5",
  "@metamask-previews/rate-limit-controller": "6.0.3-preview-510657d5",
  "@metamask-previews/remote-feature-flag-controller": "1.6.0-preview-510657d5",
  "@metamask-previews/sample-controllers": "0.1.0-preview-510657d5",
  "@metamask-previews/seedless-onboarding-controller": "1.0.0-preview-510657d5",
  "@metamask-previews/selected-network-controller": "22.1.0-preview-510657d5",
  "@metamask-previews/signature-controller": "30.0.0-preview-510657d5",
  "@metamask-previews/token-search-discovery-controller": "3.2.0-preview-510657d5",
  "@metamask-previews/transaction-controller": "57.0.0-preview-510657d5",
  "@metamask-previews/user-operation-controller": "36.0.0-preview-510657d5"
}

Copy link
Contributor

@mirceanis mirceanis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!!

I left a suggestion and a bunch of questions. Please take a look.

*/
export type SyncAddressBookEntry = AddressBookEntry & {
lastUpdatedAt?: number;
deleted?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd argue that deleted can be removed and we can use deletedAt for both.
We can also argue the reverse: Since we have a lastUpdatedAt property, we can combine that with the deleted flag to compute deletedAt.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but I prefer the 1st among your options:

  • I'll get rid of deleted (bool)
  • deletedAt absent or zero means ofc "not deleted"
  • lastUpdatedAt keeps being only about updates (and it's persisted in AddressBook unlike deletedAt)

true,
);

// Get all local contacts from AddressBookController (exclude chain "*" contacts)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why exclude chainId=='*'?
How sure are we this is the only situation with universal chainId?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure. If you look at the current implementation of AddressBookController there's never a chance a contact is stored with an unknown/wildcard chain id. Perhaps in the past that was possible, and the "pet name bridge" still uses that for "account contacts" which is out of this PR's scope.

getMessenger().call(
'AddressBookController:set',
contact.address,
contact.name || '',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think contacts with empty names should be ignored.

}
}

// SCENARIO 3 & 5: Process local contacts not in remote
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this also covers scenario 1. We should be able to shorten some of the implementation.

Comment on lines 206 to 232
// Update existing remote contacts with new contacts
const updatedRemoteContacts = [...remoteContacts];

for (const localContact of contactsToUpdateRemotely) {
const key = createContactKey(localContact);
const existingIndex = updatedRemoteContacts.findIndex(
(c) => createContactKey(c) === key,
);

const now = Date.now();
const updatedEntry = {
...localContact,
lastUpdatedAt: now,
deleted: false, // Ensure it's not deleted
} as SyncAddressBookEntry;

if (existingIndex !== -1) {
// Update existing contact
updatedRemoteContacts[existingIndex] = updatedEntry;
} else {
// Add new contact
updatedRemoteContacts.push(updatedEntry);
}
}

// Save updated contacts to remote storage
await saveContactsToUserStorage(updatedRemoteContacts, options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not send the remote contacts back if they haven't changed locally.
Starting with const updatedRemoteContacts = [...remoteContacts]; means we're always sending the entire list of contacts.
We can index by contactKey and create a list containing only the modified or new contacts like so:

Suggested change
// Update existing remote contacts with new contacts
const updatedRemoteContacts = [...remoteContacts];
for (const localContact of contactsToUpdateRemotely) {
const key = createContactKey(localContact);
const existingIndex = updatedRemoteContacts.findIndex(
(c) => createContactKey(c) === key,
);
const now = Date.now();
const updatedEntry = {
...localContact,
lastUpdatedAt: now,
deleted: false, // Ensure it's not deleted
} as SyncAddressBookEntry;
if (existingIndex !== -1) {
// Update existing contact
updatedRemoteContacts[existingIndex] = updatedEntry;
} else {
// Add new contact
updatedRemoteContacts.push(updatedEntry);
}
}
// Save updated contacts to remote storage
await saveContactsToUserStorage(updatedRemoteContacts, options);
const updatedRemoteContacts: Record<string, SyncAddressBookEntry> = {};
for (const localContact of contactsToUpdateRemotely) {
const key = createContactKey(localContact);
updatedRemoteContacts[key] = {
...remoteContactsMap.get(key), // Start with an existing remote contact if it exists
...localContact, // override with local changes
lastUpdatedAt: Date.now(), // mark as updated
deleted: false, // Ensure it's not deleted
};
}
// Save updated contacts to remote storage
await saveContactsToUserStorage(
Object.values(updatedRemoteContacts),
options,
);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. It's no longer necessary to overwrite all contacts per user/chain. I should update/delete only those who actually changed state.


return {
[USER_STORAGE_VERSION_KEY]: USER_STORAGE_VERSION,
a: toChecksumHexAddress(address),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove the checksum address here since we are going to need non-EVM contacts too

Suggested change
a: toChecksumHexAddress(address),
a: address,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that makes sense. Although a validation on hex addresses still happens in AddressBookController atm.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, but I think it's best to keep that logic there and deal with the sync assuming everything else was already validated.

userStorageEntry: UserStorageContactEntry,
): SyncAddressBookEntry => {
const addressBookEntry: SyncAddressBookEntry = {
address: toChecksumHexAddress(userStorageEntry.a),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same argument here about non-EVM.
We can let other parts of the code deal with the address validation.

Suggested change
address: toChecksumHexAddress(userStorageEntry.a),
address: userStorageEntry.a,

name: userStorageEntry.n,
chainId: userStorageEntry.c,
memo: userStorageEntry.m || '',
isEns: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens to ENS contacts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops. I forgot to map it! 🤦 Thanks! Great catch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants